<!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html lang="zh" xml:lang="zh" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<head>
<META http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Concept: 结构化类</title>
<meta name="uma.type" content="Concept">
<meta name="uma.name" content="structured_class">
<meta name="uma.presentationName" content="结构化类">
<meta name="element_type" content="concept">
<meta name="filetype" content="description">
<meta name="role" content="">
<link rel="StyleSheet" href="./../../../css/default.css" type="text/css">
<script src="./../../../scripts/ContentPageResource.js" type="text/javascript" language="JavaScript"></script><script src="./../../../scripts/ContentPageSection.js" type="text/javascript" language="JavaScript"></script><script src="./../../../scripts/ContentPageSubSection.js" type="text/javascript" language="JavaScript"></script><script src="./../../../scripts/ContentPageToolbar.js" type="text/javascript" language="JavaScript"></script><script src="./../../../scripts/contentPage.js" type="text/javascript" language="JavaScript"></script><script type="text/javascript" language="JavaScript">
					var backPath = './../../../';
					var imgPath = './../../../images/';
					var nodeInfo=null;
					contentPage.preload(imgPath, backPath, nodeInfo,  '', false, false, false);
				</script>
</head>
<body>
<div id="breadcrumbs"></div>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tr>
<td valign="top"><a name="Top"></a>
<div id="page-guid" value="1.1994826813129747E-304"></div>
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tr>
<td class="pageTitle" nowrap="true">Concept: 结构化类</td><td width="100%">
<div align="right" id="contentPageToolbar"></div>
</td><td width="100%" class="expandCollapseLink" align="right"><a name="mainIndex" href="./../../../index.htm"></a><script language="JavaScript" type="text/javascript" src="./../../../scripts/treebrowser.js"></script></td>
</tr>
</table>
<table width="100%" border="0" cellpadding="0" cellspacing="0">
<tr>
<td class="pageTitleSeparator"><img src="./../../../images/shim.gif" alt="" title="" height="1"></td>
</tr>
</table>
<div class="overview">
<table width="97%" border="0" cellspacing="0" cellpadding="0">
<tr>
<td width="50"><img src="./../../../images/concept.gif" alt="" title=""></td><td>
<table class="overviewTable" border="0" cellspacing="0" cellpadding="0">
<tr>
<td valign="top">结构化类是一种由部件组成的类（通过显式“嵌套”表示），用于对包含分层结构（它们是由部件构成的类）进行建模。</td>
</tr>
</table>
</td>
</tr>
</table>
</div>
<div class="sectionHeading">Relationships</div>
<div class="sectionContent">
<table class="sectionTable" border="0" cellspacing="0" cellpadding="0">
<tr valign="top">
<th class="sectionTableHeading" scope="row">Related Elements</th><td class="sectionTableCell">
<ul>
<li>
<a href="./../../../rup/domains/analysis_and_design_BD3BBB1D.html" guid="_kjFBYN7HEdm8G6yT7-Wdqw">分析与设计</a>
</li>
<li>
<a href="./../../../rup/workproducts/rup_design_model_2830034D.html" guid="{8CDAEAD4-5E84-4F50-87FD-3240ED047DE7}">设计模型</a>
</li>
</ul>
</td>
</tr>
</table>
</div>
<div class="sectionHeading">Main Description</div>
<div class="sectionContent">
<table class="sectionTable" border="0" cellspacing="0" cellpadding="0">
<tr valign="top">
<td class="sectionTableSingleCell"><a id="Top" name="Top"></a><a id="XE_structured_class__concepts" key="结构化类（structured class）" text="概念" name="XE_structured_class__concepts" class="index"></a>
<h3>
    <a id="Definition" name="Definition"></a>定义
</h3>
<p>
    按照 UML（[<a class="elementLinkWithUserText" href="./../../../rup/customcategories/references_56F06DFD.html#UML04" guid="7.755968586980351E-308">UML04</a>]），类是 EncapsulatedClassifier 和“元类”类的子类型，使类有能力具有内部结构和端口。此外，UML 将组件定义为类的子类型。因此，在
    NUP 环境中，我们将<strong>组件</strong>和<strong>类</strong>均视为构造化类。
</p>
<h5>
    <a id="Part" name="Part"></a>部件
</h5>
<p>
    构造的类的实例包含对应每个部件的一个或一组对象。当包含的构造类实例被破坏时，所有这样的实例都被破坏。
</p>
<p>
    以下示例显示了 Car 类的两个可能视图：
</p>
<blockquote>
    <p>
        在图（a）中，显示的 <strong>Car</strong> 具有角色名 <strong>rear</strong> 与类 <strong>Wheel</strong> 的组装关联和角色名 <strong>e</strong>
        与类 <strong>Engine</strong> 的组装关联。类 <strong>Engine</strong> 的任何实例可链接到任意数量的类 <strong>Wheel</strong> 实例。<br />
        <br />
        在图（b）中指定了同样内容。但是，在图（b）中还另外指定了以下内容：
    </p>
    <ul>
        <li>
            <p>
                <strong>rear</strong> 和 <strong>e</strong> 属于类 <strong>Car</strong> 的内部结构。这就支持详细信息的指定只适用于类
                <strong>Car</strong> 环境中的 <strong>Wheel</strong> 和 <strong>Engine</strong> 类的实例，而不适用于一般的
                <strong>wheels</strong> 和 <strong>engines</strong>。
            </p>
        </li>
        <li>
            <p>
                在类 <strong>Car</strong> 的环境内，扮演 <strong>e</strong> 角色的实例可能只连接到扮演 <strong>rear</strong> 角色的两个实例。此外，扮演
                <strong>e</strong> 和 <strong>rear</strong> 角色的实例只有在它们是类 <strong>Car</strong> 的同一个实例的角色时，才可以链接。
            </p>
        </li>
        <li style="list-style: none">
            换言之，当类 <strong>Wheel</strong> 和 <strong>Engine</strong> 的实例扮演类 <strong>Car</strong>
            的实例中各自的角色时，会对它们应用额外的约束。这些约束对于一般的 <strong>Wheel</strong> 和 <strong>Engine</strong> 的实例是不起作用的。其他
            <strong>wheel</strong> 和 <strong>engine</strong> 可按图（a）中所指定而任意链接。<br />
            <br />
        </li>
    </ul>
</blockquote>
<p align="center">
    <img src="./../../../rup/guidances/concepts/resources/parts.jpg" alt="附带文本中描述的图。" />
</p>
<p class="picturetext">
    示例：在构造的类中扮演角色的部件
</p>
<h5>
    <a id="Connector" name="Connector"></a>连接器
</h5>
<p>
    连接器是构造的类中两个部件之间的关系的实例。它是一个链接，以允许进行通信。连接器可由普通关联或瞬态关系实现，如过程参数、变量、全局值或其他机制。
</p>
<p>
    为装配连接器和委托连接器指定了构造的类的内部“配线”：
</p>
<ul>
    <li>
        在构造的类的实现中，<strong>装配连接器</strong>连接不同部件的端口。在一个构造的类的端口上发送的消息在另一个构造的类的、连接好的端口上接收。一组部件可通过各自的端口连接起来。一个部件不需要知道关于其他部件的任何信息，只需知道它们存在并符合相连接的端口的约束。构造的类之间的通信按端口建模。
    </li>
    <li style="list-style: none">
        <br />
        <br />
    </li>
    <li>
        <strong>委托连接器</strong>将构造化类的外部端口与其中一个内部部件的端口连接。由外部端口接收的消息传到内部部件的端口；由内部端口发送的消息传到外部端口，然后再传到连接该外部端口的、构造的类。
    </li>
</ul>
<h3>
    <a id="Port" name="Port"></a>端口
</h3>
<p>
    端口是构造的类的结构特性。通过强制从构造的类的外部到遵守声明接口的端口的通信来增加封装，这为该构造的类的规约和相互连接增加了精确性。
</p>
<p>
    端口需要和提供的接口指定了通过该交互点的交互必需的一切内容。如果通过端口实现构造的类与环境的所有交互，那么构造的类的内部与环境完全隔离。这使得这样一个构造的类可用于符合由端口指定的约束的任何环境。
</p>
<p>
    不存在关于端口如何实现的假定。它可作为显式对象实现，或者只是未在实现中明确出现的虚拟概念。
</p>
<p>
    下面提供了端口示例：
</p>
<h5>
    示例 1
</h5>
<p align="center">
    <img src="./../../../rup/guidances/concepts/resources/ports.jpg" alt="附带文本中描述的图。" />
</p>
<p class="picturetext">
    由 Car 和 Boat 使用的 Engine 端口
</p>
<p>
    上图显示了具有端口 <strong>p</strong> 和两个接口的类 <strong>Engine</strong>：
</p>
<ul>
    <li>
        提供的接口<strong>动力</strong>，指定了在此端口上<strong>引擎</strong>提供的服务（即，通过到达此端口的通信而可进行的操作和接收）。
    </li>
    <li>
        必需的接口<strong>电源</strong>，指定了引擎期望环境提供的服务。
    </li>
</ul>
<p>
    在端口 <strong>p</strong> 上，<strong>引擎</strong>类是完全封装的；在完全不了解引擎将嵌入的环境的情况下也可以指定它。只要环境遵守引擎的提供和需要的接口所指出的约束，引擎就将正确运行。<br />
    <br />
    为了解释这一点，此示例显示了 <strong>Engine</strong> 类的两种使用：
</p>
<ul>
    <li>
        <strong>Car</strong> 类通过 <strong>axle</strong> 连接 engine 端口 <strong>p</strong> 和一组 wheel。
    </li>
    <li>
        <strong>Boat</strong> 类通过 <strong>shaft</strong> 连接 engine 端口 <strong>p</strong> 和 propeller。
    </li>
</ul>
<p>
    只要<strong>引擎</strong>和链接到其端口 <strong>p</strong> 的部件之间的交互遵循约束（由提供的和需要的接口指定），引擎就将按指定运行，无论它是汽车引擎还是船引擎。
</p>
<p>
    而且，即使 <strong>Engine</strong> 具有其他声明的端口，如用于 <strong>Fuel Consumption</strong> 的端口 <strong>f</strong>，汽车的车轮和船的螺旋桨仍将通过端口
    <strong>p</strong> 访问 <strong>Engine</strong>。端口 <strong>f</strong> 将是燃料表所感兴趣的，不管使用的燃料类型以及汽车和船可能具有的燃料表类型如何。
</p>
<h5>
    示例 2
</h5>
<p>
    此端口示例是基于 Java Logging API（[<a class="elementLinkWithUserText" href="./../../../rup/customcategories/references_56F06DFD.html#JAV03" guid="7.755968586980351E-308">JAV03</a>]）的，后者是提供
    Java 2 平台的核心日志记录工具的以下类和接口的包，其中：
</p>
<ul>
    <li style="list-style: none">
        <strong>记录器</strong>是应用程序作出日志记录调用的主要实体。它用于为特定系统或应用程序组件记录消息
    </li>
    <li style="list-style: none">
        <strong>级别</strong>提供了日志消息的重要性和紧迫性的指示信息
    </li>
    <li style="list-style: none">
        <strong>过滤器</strong>提供了记录内容的细分控制，超出了日志级别提供的控制
    </li>
    <li style="list-style: none">
        <strong>处理程序</strong>从记录器调取消息并将它们导出到不同目标位置（内存、输出流、控制台、文件和套接字）
    </li>
    <li style="list-style: none">
        <strong>格式化程序</strong>支持日志记录的格式化
    </li>
</ul>
<p>
    那些类和接口在两种重要类型的协作中牵涉到。某些类和接口用于写入日志，而其他类和接口用于管理日志。下图显示了客户和管理员使用日志的两种不同协作，建模成 UML 协作：
</p>
<ul>
    <li style="list-style: none">
        <strong>写</strong>协作，其中 <strong>LogClient</strong> 角色连接到 <strong>LogWriter</strong> 角色，以便写入日志。
    </li>
    <li style="list-style: none">
        <strong>管理</strong>协作，其中 <strong>LogAdministrator</strong> 角色连接到 <strong>LogController</strong>
        角色，以便访问日志和更改日志设置。<br />
    </li>
</ul>
<p align="center">
    <img src="./../../../rup/guidances/concepts/resources/collab.gif" alt="附带文本中描述的图。" />
</p>
<p class="picturetext">
    客户和管理员使用日志的不同协作
</p>
<p>
    对日志记录服务及其协作建模的一种可能的 UML 2.0 表示将使用具有端口和声明接口的组件，如下图所示：
</p>
<p align="center">
    <img src="./../../../rup/guidances/concepts/resources/ports1.gif" alt="附带文本中描述的图。" />
</p>
<p class="picturetext">
    作为组件实现的 Java 日志记录 API 包，提供分组到端口中的接口
</p>
<p>
    在 Java 日志记录 API
    规约中，一部分日志记录服务被作为类实现，而其他日志记录服务作为接口实现。在此示例中，我们将每个这些服务作为提供的接口建模，这可在组件内部由部件实现。上面提到的与<strong>写</strong>和<strong>管理</strong>协作相关的、两个不同种类的行为可用逻辑上分组到端口中的接口来表示。因此，我们将：
</p>
<ul>
    <li style="list-style: none">
        <strong>Logger</strong> 和 <strong>Level</strong> 接口分组到 <strong>LogWriter</strong>
        端口中。由<strong>日志客户机</strong>访问这些端口，从而写入<strong>日志</strong>。
    </li>
    <li style="list-style: none">
        <strong>Handler</strong>、<strong>Filter</strong> 和 <strong>Formatter</strong> 接口分组到 <strong>LogController</strong>
        端口中。由日志管理员访问那些接口，来访问日志和更改日志设置。
    </li>
</ul>
<p>
    此建模备选方案通过在逻辑上将接口分组到不同端口中而分离了问题。我们为组件规约和它与外部世界的相互连接提供了额外的精确性。
</p>
<h3>
    <a id="Modeling" name="Modeling"></a>建模
</h3>
<p>
    在设计期间，类和组件可分解成相连接的部件的集合（可依次进一步分解）。
</p>
<p>
    <strong>组合结构图</strong>可用于显示构造的类的分解。作为示例，下图显示了售票系统中票房的组合结构图。此类分解成三个部件：
</p>
<ul>
    <li>
        票销售员接口
    </li>
    <li>
        按照日期和其他条件检索性能的性能指示信息
    </li>
    <li>
        包含关于性能和门票的数据的一组数据库。
    </li>
</ul>
<p>
    每个部件通过由各自的端口指定的、定义良好的接口来进行交互。整个票房通过端口与外界交互。此端口上的消息被分派到票销售员类，但票房类的内部结构对于外部客户是不可见的。
</p>
<p align="center">
    <img src="./../../../rup/guidances/concepts/resources/structclass.gif" alt="附带文本中描述的图。" />
</p>
<p class="picturetext">
    示例：售票系统的组合结构图。
</p>
<h3>
    <a id="UML 1.x Representation" name="UML 1.x Representation"></a>UML1.x 表示法
</h3>
<p>
    请注意，构造的类在 UML 2.0 中是一个新概念。
</p>NUP 定义的很多封装体可使用结构化类来表示（有关该主题的更多信息，请参阅<a class="elementLinkWithType" href="./../../../rup/workproducts/rup_capsule_FC4A34FD.html" guid="{4423FCE1-FF59-4C8E-A6C4-AA4B13CB3250}">Artifact: 封装体</a>和<a class="elementLinkWithType" href="./../../../rup/guidances/guidelines/capsule_7077C999.html" guid="7.026940817483919E-306">Guideline: 封装体</a>）。 
<p>
    如果您的工具只支持 UML 1.5，在<a class="elementLinkWithType" href="./../../../rup/workproducts/rup_capsule_FC4A34FD.html" guid="{4423FCE1-FF59-4C8E-A6C4-AA4B13CB3250}">Artifact: 封装体</a>和<a class="elementLinkWithType" href="./../../../rup/guidances/guidelines/capsule_7077C999.html" guid="7.026940817483919E-306">Guideline: 封装体</a>中还讨论了备选的表示法。
</p>
<p>
    关于更多信息，请参阅<a class="elementLink" href="./../../../rup/guidances/supportingmaterials/differences_between_uml_1_x_and_uml_2_0_CA70F2E6.html" guid="4.792914878943572E-306">UML 1.x 和 UML 2.0 之间的区别</a>。<br />
</p><br />
<br /></td>
</tr>
</table>
</div>
<table class="copyright" border="0" cellspacing="0" cellpadding="0">
<tr>
<td class="copyright">Copyright &copy; 2008 版权所有 东软集团股份有限公司&nbsp; 联系邮箱:<a href="mailto:tcoe@neusoft.com">tcoe@neusoft.com</a></td>
</tr>
</table>
</td>
</tr>
</table>
</body>
<script type="text/javascript" language="JavaScript">
				contentPage.onload();
			</script>
</html>
